package dynamic

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"os"
	"strings"
	"sync"
	"time"
	"vrcm/src/vrcm/app/admin/models/dynamic"
	"vrcm/src/vrcm/app/consts"
	"vrcm/src/vrcm/app/do/remote_request"
	"vrcm/src/vrcm/app/do/remote_response"
	"vrcm/src/vrcm/app/do/request"
	"vrcm/src/vrcm/common/service"
	"vrcm/src/vrcm/common/whttp"
	"vrcm/src/vrcm/common/wtools"
	ext "vrcm/src/vrcm/envconfig"
)

var (
	ngvsaErr       = errors.New("Get Res Ngvsa Err")
	dbErr          = errors.New("DB Err")
	targetNotExist = errors.New("记录不存在")
	targetExist    = errors.New("实例名称已存在")
	domainExist    = errors.New("domain 加速配置已存在")
	ipExist        = errors.New("ip 加速配置已存在")
	pakIdExist     = errors.New("套餐已使用")

	createPath    = "/v1/rtt/delivery"
	portPath      = "/v1/ann_service/avaliable_port/"
	delPath       = "/v1/rtt/delivery/"
	updatePath    = "/v1/rtt/delivery/"
	recoverPath   = "/v1/rtt/delivery/"
	porxyPortPath = "/v1/rtt/port"
	statusPath    = "/v1/rtt/delivery/"

	vrbmOrderList = "/v1/order/user/onTimeList"

	splitTag  = ","
	domainTag = ">>"
	urlTag    = "/"
	innerTag  = "%s %s %s"
	spaceTag  = " "
	outTag    = "\n"

	rootDomainMap = make(map[string]string)
	once          = sync.Once{}
)

type DynamicServer struct {
	service.Service
}

// DynamicList 列表
func (this DynamicServer) DynamicList(c *gin.Context, req request.DynamicList) (interface{}, error) {
	var (
		res   = make(map[string]interface{})
		tmp   = make([]dynamic.Dynamic, 0)
		count int64
	)
	db := this.Orm.Model(dynamic.Dynamic{})
	if req.Status > 0 {
		db.Where("status = ?", req.Status)
	}
	if req.TenantId != "" {
		db.Where("tenantId = ?", req.TenantId)
	}
	if req.VSTenantId != "" {
		db.Where("vsTenantId = ?", req.VSTenantId)
	}
	err := db.Count(&count).
		Offset((req.PageIndex - 1) * req.PageSize).
		Limit(req.PageSize).
		Find(&tmp).Error
	stuct := this.sqlToStuct(tmp)
	res["list"] = stuct
	res["page_index"] = req.PageIndex
	res["page_size"] = req.PageSize
	res["total"] = count
	return res, err
}

// TimeRefreshTaskState 定时刷新任务状态
func (this DynamicServer) TimeRefreshTaskState() {
	var (
		tmp = make([]dynamic.Dynamic, 0)
	)
	err := this.Orm.Model(dynamic.Dynamic{}).
		Where("status = ?", consts.SPending).
		Find(&tmp).
		Error
	if err != nil {
		// 等待状态
		this.Log.Error("TimeRefreshTaskState Get Dynamic SPending List Err: " + err.Error())
		return
	}
	for _, v := range tmp {
		var (
			dLog = make([]dynamic.DynamicInstance, 0)
		)
		ngvsaIds := this.getNgvsaIds(v.OriginIds)
		err = this.Orm.Model(dynamic.DynamicInstance{}).
			Where("instanceId = ?", v.InstanceId).
			Where("ngvsaInstanceId IN ?", ngvsaIds).
			Find(&dLog).Error
		if err != nil {
			this.Log.Error("TimeRefreshTaskState Get DynamicInstance List Err: " + err.Error())
			continue
		}
		status := 0
		for _, vv := range dLog {
			ngvsaRes, err := this.rttDellivery(vv.NgvsaInstanceId, vv.TenantId)
			if err != nil {

			}
			if ngvsaRes.Code != 200 {
				this.Log.Errorf("DynamicInfo-TimeRefreshTaskState whttp.HandleResponse Code error:(%s) %v \r\n", vv.NgvsaInstanceId, ngvsaRes)
				continue
			}
			if ngvsaRes.Data.CcState == "processing" && status != consts.SFail {
				status = consts.SPending
			}
			if ngvsaRes.Data.CcState == "failure" {
				status = consts.SFail
			}
			// 更新每条记录状态
			err = this.Orm.Model(dynamic.DynamicInstance{}).
				Where("id = ?", vv.ID).
				Select("status", "failMsg").
				Updates(&dynamic.DynamicInstance{
					Status:  ngvsaRes.Data.CcState,
					FailMsg: ngvsaRes.Data.CcMessage,
				}).Error
			if err != nil {
				this.Log.Errorf("DynamicInfo-TimeRefreshTaskState Orm error: %v \r\n", err)
			}
		}
		if status == 0 {
			status = consts.SRunning
		}
		this.Orm.Model(dynamic.Dynamic{}).
			Where("id = ?", v.Id).
			Update("status", status)
	}
}

// DynamicInfo 列表
func (this DynamicServer) DynamicInfo(c *gin.Context, req request.DynamicInfo) (interface{}, error) {
	var (
		tmp = dynamic.Dynamic{}
	)
	err := this.Orm.Model(dynamic.Dynamic{}).
		Where("id = ?", req.Id).
		Find(&tmp).Error
	finalRes := this.sqlToStuctSingle(tmp)
	//finalRes := this.setSingleWithSystemTag(tmp, stuct)
	return finalRes, err
}

// DynamicStopOrRecover 启用或禁用
func (this DynamicServer) DynamicStopOrRecover(c *gin.Context, req request.DynamicStop) (interface{}, error) {
	info, err := this.exist(req.Id)
	if err != nil {
		return nil, err
	}
	if info.Id <= 0 {
		return nil, targetNotExist
	}
	ids := this.getIds(info.OriginIds)
	for key, _ := range ids {
		var (
			path string
		)
		if req.Action == consts.SRunning {
			path = recoverPath + ids[key] + "/start"
		} else if req.Action == consts.SStopping {
			path = recoverPath + ids[key] + "/stop"
		} else {
			return nil, errors.New("Action Err")
		}
		hClient := this.getClient()
		r, err := hClient.PutJSON(path, struct{}{})
		if err != nil {
			this.Log.Errorf("DynamicStopOrRecover hClient.Delete error:(%s) %s \r\n", ids[key], err)
			return nil, err
		}
		response, err := whttp.HandleResponse(r)
		if err != nil {
			this.Log.Errorf("DynamicStopOrRecover whttp.HandleResponse error:(%s) %s \r\n", ids[key], err)
			return nil, err
		}
		res := remote_response.DynamicPostRes{}
		json.Unmarshal(response, &res)
		if res.Code != 200 {
			this.Log.Errorf("DynamicStopOrRecover whttp.HandleResponse Code error:(%s) %v \r\n", ids[key], res)
			return nil, ngvsaErr
		}
		time.Sleep(time.Millisecond * 50)
	}
	err = this.Orm.Model(dynamic.Dynamic{}).
		Where("id = ?", req.Id).
		Select("update_time", "status").
		Updates(&dynamic.Dynamic{
			UpdateTime: time.Now(),
			Status:     req.Action,
		}).
		Error
	if err != nil {
		this.Log.Errorf("DynamicStopOrRecover Orm error: %v \r\n", err)
		return nil, dbErr
	}
	return nil, nil
}

// DynamicUpdate 编辑
func (this DynamicServer) DynamicUpdate(c *gin.Context, req request.DynamicEdit) (interface{}, error) {
	exist, err2 := this.existDomain(req.Id, req)
	if err2 != nil {
		return nil, err2
	}
	if exist {
		if req.DynamicType == consts.DynamicDomainType {
			return nil, domainExist
		}
		return nil, ipExist
	}
	exist2, err2 := this.existPakId(req.Id, req.PackageId)
	if err2 != nil {
		return nil, err2
	}
	if exist2 {
		return nil, pakIdExist
	}
	var (
		tmp = dynamic.Dynamic{}
	)
	err := this.Orm.Model(dynamic.Dynamic{}).
		Where("id = ?", req.Id).
		Find(&tmp).Error
	if err != nil {
		this.Log.Errorf("DynamicUpdate Orm Find error: %v \r\n", err)
		return nil, dbErr
	}
	if tmp.Id <= 0 {
		return nil, targetNotExist
	}
	// origin
	stuct := this.sqlToStuctSingle(tmp)
	added, removed, common := this.compareDynamicRules(stuct, req)
	idMap := this.getIds(tmp.OriginIds)

	var (
		newIds    string
		commonIds string
	)
	reqFormat := this.formatDomainReqData(req, tmp.Cname)

	// add
	for key, _ := range reqFormat {
		for _, v := range added {
			if key > 0 && (v.Protocol == consts.ProtocolTCP || v.Protocol == consts.ProtocolUdp) {
				continue
			}
			t := make([]remote_request.PortList, 0, 1)
			tm := remote_request.PortList{
				Id:         v.DynamicPort,
				OriginPort: v.OriginPort,
				AccessPort: v.DynamicPort,
				Type:       v.Protocol,
			}
			if v.Protocol == consts.ProtocolHttp {
				tm.SslEnable = "no"
			} else {
				tm.SslEnable = "yes"
			}
			t = append(t, tm)
			reqFormat[key].PortLists = t
			hClient := this.getClient()
			r, err := hClient.PostJSON(createPath, reqFormat[key])
			if err != nil {
				this.Log.Errorf("Request Data is: %v \r\n", reqFormat[key])
				this.Log.Errorf("DynamicEdit hClient.PostJSON error: %s \r\n", err)
				return nil, err
			}
			response, err := whttp.HandleResponse(r)
			if err != nil {
				this.Log.Errorf("DynamicEdit whttp.HandleResponse error: %s \r\n", err)
				return nil, err
			}
			res := remote_response.DynamicCreateRes{}
			json.Unmarshal(response, &res)
			if res.Code != 200 {
				this.Log.Errorf("DynamicEdit whttp.HandleResponse error: %v \r\n", string(response))
				return nil, ngvsaErr
			}
			if v.Protocol == consts.ProtocolTCP || v.Protocol == consts.ProtocolUdp {
				newIds += (reqFormat[key].RequestDomain + domainTag + v.Protocol + v.DynamicPort + domainTag + res.Data.Id + splitTag)
				//newIds += (domainTag + v.Protocol + v.DynamicPort + domainTag + res.Data.Id + splitTag)
			} else {
				newIds += (reqFormat[key].RequestDomain + domainTag + v.Protocol + domainTag + res.Data.Id + splitTag)
			}
			if tmp.Cname == "" {
				if v.Protocol == consts.ProtocolTCP || v.Protocol == consts.ProtocolUdp {
					tmp.Cname = reqFormat[key].RequestDomain
				} else {
					tmp.Cname = res.Data.Cname
				}
			}
			time.Sleep(time.Millisecond * 50)
		}
	}

	// remove
	for key, _ := range removed {
		for k, v := range idMap {
			if strings.Contains(k, domainTag+removed[key].Protocol+removed[key].DynamicPort+domainTag) || strings.Contains(k, domainTag+removed[key].Protocol+domainTag) {
				hClient := this.getClient()
				r, err := hClient.Delete(delPath + v)
				if err != nil {
					this.Log.Errorf("DynamicDelete hClient.Delete error:(%s) %s \r\n", v, err)
					return nil, err
				}
				response, err := whttp.HandleResponse(r)
				if err != nil {
					this.Log.Errorf("DynamicDelete whttp.HandleResponse error:(%s) %s \r\n", v, err)
					return nil, err
				}
				res := remote_response.DynamicPostRes{}
				json.Unmarshal(response, &res)
				if res.Code != 200 {
					this.Log.Errorf("DynamicDelete whttp.HandleResponse Code error: %v \r\n", string(response))
					return nil, ngvsaErr
				}
				time.Sleep(time.Millisecond * 50)
			}
		}
	}

	// update
	//fmt.Println("===> reqFormat", reqFormat)
	//fmt.Println("===> idMap", idMap)
	for key, _ := range reqFormat {
		for _, v := range common {
			if key > 0 && (v.Protocol == consts.ProtocolTCP || v.Protocol == consts.ProtocolUdp) {
				continue
			}
			t := make([]remote_request.PortList, 0, 1)
			tm := remote_request.PortList{
				Id:         v.DynamicPort,
				OriginPort: v.OriginPort,
				AccessPort: v.DynamicPort,
				Type:       v.Protocol,
			}
			if v.Protocol == consts.ProtocolHttp {
				tm.SslEnable = "no"
			} else {
				tm.SslEnable = "yes"
			}
			t = append(t, tm)
			reqFormat[key].PortLists = t
			if v.Protocol == consts.ProtocolTCP || v.Protocol == consts.ProtocolUdp {
				if k, ok := idMap[reqFormat[key].RequestDomain+domainTag+v.Protocol+v.DynamicPort+domainTag]; ok {
					reqFormat[key].Id = k
					commonIds += reqFormat[key].RequestDomain + domainTag + v.Protocol + v.DynamicPort + domainTag + k + splitTag
				}
			} else {
				if k, ok := idMap[reqFormat[key].RequestDomain+domainTag+v.Protocol+domainTag]; ok {
					reqFormat[key].Id = k
					commonIds += reqFormat[key].RequestDomain + domainTag + v.Protocol + domainTag + k + splitTag
				}
			}
			hClient := this.getClient()
			r, err := hClient.PutJSON(updatePath+reqFormat[key].Id, reqFormat[key])
			if err != nil {
				this.Log.Errorf("Request Data is: %v \r\n", reqFormat[key])
				this.Log.Errorf("DynamicEdit hClient.PutJSON error: %s \r\n", err)
				return nil, err
			}
			response, err := whttp.HandleResponse(r)
			if err != nil {
				this.Log.Errorf("DynamicEdit whttp.HandleResponse error: %s \r\n", err)
				return nil, err
			}
			res := remote_response.DynamicCreateRes{}
			json.Unmarshal(response, &res)
			if res.Code != 200 {
				this.Log.Errorf("DynamicEdit whttp.HandleResponse error: %v \r\n", string(response))
				return nil, ngvsaErr
			}
			time.Sleep(time.Millisecond * 50)
		}
	}

	tx := this.Orm.Begin()
	defer tx.Rollback()
	err = tx.Model(dynamic.Dynamic{}).
		Where("id = ?", req.Id).
		Delete(&dynamic.Dynamic{}).Error
	if err != nil {
		return nil, dbErr
	}
	oldTag := dynamic.Dynamic{
		InstanceId:     tmp.InstanceId,
		InstanceName:   tmp.InstanceName,
		Id:             req.Id,
		ExpirationTime: tmp.ExpirationTime,
		VSTenantId:     tmp.VSTenantId,
	}
	fields := this.convertToMySQLFields(req, newIds+commonIds, tmp.Cname, oldTag, "", consts.SPending)
	fields.Id = req.Id
	err = tx.Model(&dynamic.Dynamic{}).Create(&fields).Error
	if err != nil {
		return nil, dbErr
	}
	tx.Commit()
	idMap = this.getIds(newIds + commonIds)
	err = this.createDILog(req, tmp.InstanceId, idMap, tmp.Cname, tmp.VSTenantId)
	if err != nil {
		return nil, err
	}
	return nil, nil
}

// DynamicCreate 创建
func (this DynamicServer) DynamicCreate(c *gin.Context, req request.DynamicEdit) (interface{}, error) {
	return nil, nil
	//exist, err2 := this.existDomain(0, req)
	//if err2 != nil {
	//	return nil, err2
	//}
	//if exist {
	//	return nil, domainExist
	//}
	//exist2, err2 := this.existPakId(0, req.PackageId)
	//if err2 != nil {
	//	return nil, err2
	//}
	//if exist2 {
	//	return nil, pakIdExist
	//}
	//reqData := this.formatDomainReqData(req)
	//var (
	//	ids, cname string
	//)
	//for key, _ := range reqData {
	//	for _, v := range reqData[key].PortLists {
	//		t := make([]remote_request.PortList, 0, 1)
	//		t = append(t, v)
	//		reqData[key].PortLists = t
	//		hClient := this.getClient()
	//		r, err := hClient.PostJSON(createPath, reqData[key])
	//		if err != nil {
	//			this.Log.Errorf("Request Data is: %v \r\n", reqData[key])
	//			this.Log.Errorf("DynamicEdit hClient.PostJSON error: %s \r\n", err)
	//			return nil, err
	//		}
	//		response, err := whttp.HandleResponse(r)
	//		fmt.Println("ngvsa-response", string(response))
	//		if err != nil {
	//			this.Log.Errorf("DynamicEdit whttp.HandleResponse error: %s \r\n", err)
	//			return nil, err
	//		}
	//		res := remote_response.DynamicCreateRes{}
	//		json.Unmarshal(response, &res)
	//		if res.Code != 200 {
	//			this.Log.Errorf("DynamicEdit whttp.HandleResponse error: %v \r\n", res)
	//			return nil, ngvsaErr
	//		}
	//		if key == 0 {
	//			cname = res.Data.Cname
	//		}
	//		// www.baidu.com>>ssl>>40a81260-05cb-46a0-8583-c89c3a5b0a6c,
	//		ids += (reqData[key].RequestDomain + domainTag + v.Type + domainTag + res.Data.Id + splitTag)
	//		time.Sleep(time.Millisecond * 50)
	//	}
	//}
	//uid := uuid.NewString()
	//fields := this.convertToMySQLFields(req, ids, cname, dynamic.Dynamic{}, uid)
	//err := this.Orm.Model(dynamic.Dynamic{}).Create(&fields).Error
	//if err != nil {
	//	return nil, err
	//}
	//err = this.createDILog(req, uid)
	//if err != nil {
	//	return nil, err
	//}
	//return nil, nil
}

// DynamicDelete 删除
func (this DynamicServer) DynamicDelete(c *gin.Context, req request.DynamicDel) (interface{}, error) {
	var (
		res = dynamic.Dynamic{}
	)
	err := this.Orm.Model(dynamic.Dynamic{}).
		Where("id = ?", req.Id).
		Find(&res).
		Error
	if err != nil {
		return nil, err
	}
	if res.Id <= 0 {
		return nil, targetNotExist
	}
	ids := this.getIds(res.OriginIds)
	for key, _ := range ids {
		hClient := this.getClient()
		r, err := hClient.Delete(delPath + ids[key])
		if err != nil {
			this.Log.Errorf("DynamicDelete hClient.Delete error:(%s) %s \r\n", ids[key], err)
			return nil, err
		}
		response, err := whttp.HandleResponse(r)
		if err != nil {
			this.Log.Errorf("DynamicDelete whttp.HandleResponse error:(%s) %s \r\n", ids[key], err)
			return nil, err
		}
		res := remote_response.DynamicPostRes{}
		json.Unmarshal(response, &res)
		if res.Code != 200 {
			this.Log.Errorf("DynamicDelete whttp.HandleResponse Code error: %v \r\n", res)
			return nil, ngvsaErr
		}
		time.Sleep(time.Millisecond * 50)
	}
	if req.DelType == consts.ActionDel {
		err = this.Orm.Model(dynamic.Dynamic{}).
			Where("id = ?", req.Id).
			Delete(&dynamic.Dynamic{}).
			Error
		if err != nil {
			return nil, err
		}
		return nil, nil
	}
	fields := dynamic.Dynamic{
		Status:                  consts.STrans,
		Id:                      req.Id,
		DynamicType:             "",
		Domains:                 "",
		OriginStations:          "",
		Position:                "",
		Topo:                    "",
		ProxyProtocolEnable:     "",
		DisableOriginPortHeader: "",
		IsIcp:                   "",
		Rules:                   "",
		OriginIds:               "",
		OriginIdInfo:            "",
		Cname:                   "",
		UpdateTime:              time.Now(),
		ExpirationTime:          res.ExpirationTime,
	}
	err = this.Orm.Model(dynamic.Dynamic{}).
		Where("id = ?", req.Id).
		Select("dynamicType", "domains", "originStations", "position",
			"rules", "status", "originIds", "cname", "update_time", "expiration_time", "topo", "isIcp",
			"proxyProtocolEnable", "disableOriginPortHeader").
		Updates(&fields).
		Error
	if err != nil {
		return nil, err
	}
	return nil, nil
}

// DynamicGetPort 获取端口
func (this DynamicServer) DynamicGetPort(c *gin.Context, req request.DynamicGetPort) (interface{}, error) {
	hClient := this.getClient()
	var (
		param string
	)
	if req.Num != "" {
		param = req.Protocol + "?num=" + req.Num
	} else {
		param = req.Protocol
	}
	r, err := hClient.Get(portPath + param)
	if err != nil {
		this.Log.Errorf("DynamicGetPort hClient.Get error: %s \r\n", err)
		return nil, err
	}
	response, err := whttp.HandleResponse(r)
	if err != nil {
		this.Log.Errorf("DynamicGetPort whttp.HandleResponse error: %s \r\n", err)
		return nil, err
	}
	res := remote_response.DynamicPostRes{}
	json.Unmarshal(response, &res)
	if res.Code != 200 {
		this.Log.Errorf("DynamicGetPort whttp.HandleResponse Code error: %v \r\n", res)
		return nil, ngvsaErr
	}
	return res.Data, nil
}

func (this DynamicServer) rttDellivery(id, tenantId string) (*remote_response.DynamicNgvsaStatus, error) {
	hClient := this.getClient()
	path := statusPath + id + "?tenant_id=" + tenantId
	r, err := hClient.Get(path)
	if err != nil {
		this.Log.Errorf("DynamicGetStatus-rttDellivery hClient.Get error: %s \r\n", err)
		return nil, err
	}
	response, err := whttp.HandleResponse(r)
	if err != nil {
		this.Log.Errorf("DynamicGetStatus-rttDellivery whttp.HandleResponse error: %s \r\n", err)
		return nil, err
	}
	res := remote_response.DynamicNgvsaStatus{}
	json.Unmarshal(response, &res)
	if res.Code != 200 {
		this.Log.Errorf("DynamicGetStatus-rttDellivery whttp.HandleResponse Code error: %v \r\n", res)
		return nil, ngvsaErr
	}
	return &res, nil
}

func (this DynamicServer) DynamicCheckPort(c *gin.Context, req request.DynamicCheckPort) (interface{}, error) {
	var (
		param string
	)
	/*
		检查四层tcp
		{{ngvsa_address}}/v1/ann_service/avaliable_port/layer4check?ports=1111,1021,102
		检查四层udp
		{{ngvsa_address}}/v1/ann_service/avaliable_port/layer4udpcheck?ports=1111,1029,102
	*/
	hClient := this.getClient()
	if req.Protocol == consts.ProtocolTCP {
		param = "layer4check?ports=" + req.Ports
	} else if req.Protocol == consts.ProtocolUdp {
		param = "layer4udpcheck?ports=" + req.Ports
	}
	r, err := hClient.Get(portPath + param)
	if err != nil {
		this.Log.Errorf("DynamicCheckPort hClient.Get error: %s \r\n", err)
		return nil, err
	}
	response, err := whttp.HandleResponse(r)
	if err != nil {
		this.Log.Errorf("DynamicCheckPort whttp.HandleResponse error: %s \r\n", err)
		return nil, err
	}
	res := remote_response.DynamicPostRes{}
	json.Unmarshal(response, &res)
	if res.Code != 200 {
		this.Log.Errorf("DynamicCheckPort whttp.HandleResponse Code error: %v \r\n", res)
		return nil, errors.New(res.Message)
	}
	return nil, nil
}

// DynamicUInstName 更新实例名称
func (this DynamicServer) DynamicUInstName(c *gin.Context, req request.DynamicUInstName) (interface{}, error) {
	var (
		tmp  = dynamic.Dynamic{}
		ntmp = dynamic.Dynamic{}
	)
	err := this.Orm.Model(dynamic.Dynamic{}).
		Where("id = ?", req.Id).
		Find(&tmp).Error
	if err != nil {
		this.Log.Errorf("DynamicUpdate Orm Find error: %v \r\n", err)
		return nil, dbErr
	}
	if tmp.Id <= 0 {
		return nil, targetNotExist
	}
	err = this.Orm.Model(dynamic.Dynamic{}).
		Where("tenantId = ?", req.TenantId).
		Where("instanceName = ?", req.InstanceName).
		Where("id != ?", req.Id).
		Find(&ntmp).Error
	if err != nil {
		this.Log.Errorf("DynamicUpdate Orm Find error: %v \r\n", err)
		return nil, dbErr
	}
	if ntmp.Id > 0 {
		return nil, targetExist
	}
	if tmp.InstanceName != req.InstanceName {
		err = this.Orm.Model(dynamic.Dynamic{}).
			Where("id = ?", req.Id).
			Update("instanceName", req.InstanceName).
			Error
		if err != nil {
			this.Log.Errorf("DynamicUpdate Orm Update error: %v \r\n", err)
			return nil, dbErr
		}
	}
	return nil, nil
}

// DynamicPackageList 订单列表
func (this DynamicServer) DynamicPackageList(c *gin.Context, req request.DynamicPackageList) (interface{}, error) {
	res, err := this.orderList(req.TenantId, "")
	if err != nil {
		return nil, err
	}
	var (
		tmp = make([]dynamic.Dynamic, 0)
		tm  = make(map[string]struct{})
	)
	err = this.Orm.Model(dynamic.Dynamic{}).
		Where("tenantId = ?", req.TenantId).
		Find(&tmp).
		Error
	if err != nil {
		this.Log.Errorf("DynamicPackageList Orm Find error: %v \r\n", err)
		return nil, dbErr
	}
	for _, val := range tmp {
		if _, ok := tm[val.PackageId]; !ok {
			tm[val.PackageId] = struct{}{}
		}
	}
	var (
		finalRes = make([]remote_response.VrbmDta, 0)
	)
	for key, _ := range res.Data {
		if _, ok := tm[res.Data[key].OrderId]; !ok {
			finalRes = append(finalRes, res.Data[key])
		}
	}
	if len(finalRes) == 0 {
		return nil, errors.New("暂无可用套餐, 请联系管理员订购!")
	}
	return finalRes, nil
}

// DynamicPackageInfo 订单详情
func (this DynamicServer) DynamicPackageInfo(c *gin.Context, req request.DynamicPackageInfo) (interface{}, error) {
	var (
		res = dynamic.Dynamic{}
	)
	err := this.Orm.Model(dynamic.Dynamic{}).
		Where("id = ?", req.Id).
		Find(&res).
		Error
	if err != nil {
		return nil, err
	}
	if res.Id <= 0 {
		return nil, targetNotExist
	}
	if res.PackageId != req.PackageId {
		return nil, errors.New("套餐ID不匹配!")
	}
	list, err := this.orderList(req.TenantId, req.PackageId)
	if err != nil {
		return nil, err
	}

	var (
		finalRes = make([]remote_response.VrbmDta, 0)
	)
	for key, _ := range list.Data {
		if list.Data[key].OrderId == res.PackageId {
			finalRes = append(finalRes, list.Data[key])
		}
	}
	if len(finalRes) == 0 {
		return nil, errors.New("套餐不可用")
	}
	return finalRes, nil
}

func (this DynamicServer) formatDomainReqData(req request.DynamicEdit, cname string) []remote_request.DynamicCreate {
	var (
		res       = make([]remote_request.DynamicCreate, 0)
		source    []remote_request.Source
		portLists []remote_request.PortList
		d         string
	)
	if req.Domains == "" {
		// 这里 ip 加速, 主动生成 cname, 六位随机数
		if cname != "" {
			d = cname
		} else {
			d = getOwnDomain(req.TenantId, req.VSTenantId)
		}
		var tmp = this.getBasicInfo(req, d, req.Position, req.SchedulePolicy)
		tmp.Sources = this.formatSources(req.OriginStations, req.DynamicType, req.Position)
		tmp.PortLists = this.formatPortLists(req.Rules)
		res = append(res, tmp)
		return res
	}
	domains := strings.Split(req.Domains, splitTag)
	for key, val := range domains {
		var tmp = this.getBasicInfo(req, val, req.Position, req.SchedulePolicy)
		if key == 0 {
			source = this.formatSources(req.OriginStations, req.DynamicType, req.Position)
			portLists = this.formatPortLists(req.Rules)
			tmp.Sources = source
			tmp.PortLists = portLists
		} else {
			tmp.Sources = source
			tmp.PortLists = this.dealPostList(portLists)
		}
		res = append(res, tmp)
	}
	// debug
	//marshal, _ := json.Marshal(res)
	//fmt.Println("reqData", string(marshal), "\n\r")
	return res
}

func (this DynamicServer) getBasicInfo(req request.DynamicEdit, d, p, sp string) remote_request.DynamicCreate {
	return remote_request.DynamicCreate{
		Topo:                p,
		RequestDomain:       d,
		CnameScheduleEnable: "yes",
		RenterID:            req.TenantId,
		TenantId:            req.Account,
		ServiceIpIndex:      "0",
		Parameters: remote_request.Parameters{
			ProxyProtocolEnable:     req.ProxyProtocolEnable,
			DisableOriginPortHeader: req.DisableOriginPortHeader,
		},
		PublishDomain:        "",
		SchedulePolicy:       sp,
		GlobalDomain:         "",
		PublishHostname:      "",
		WildcardDomainEnable: "yes",
	}
}

func (d DynamicServer) formatSources(req []request.OriginStation, t, p string) []remote_request.Source {
	var (
		res     = make([]remote_request.Source, 0)
		tmp     = remote_request.Source{}
		active  = make([]string, 0)
		standby = make([]string, 0)
	)
	tmp = remote_request.Source{
		ServerMode:     "active",
		Servers:        nil,
		StandbyServers: nil,
		Type:           t,
		OriginDc:       "shanghai",
		Matches:        0,
		Rule:           0,
		Algorithm:      "hash",
	}

	for _, val := range req {
		if val.IsMaster == consts.IsMaster {
			active = append(active, val.Address)
			continue
		}
		standby = append(standby, val.Address)
	}
	tmp.Servers = active
	tmp.StandbyServers = standby
	res = append(res, tmp)
	return res
}

func (d DynamicServer) formatPortLists(req []request.DynamicRule) []remote_request.PortList {
	var (
		res = make([]remote_request.PortList, 0)
	)
	for _, val := range req {
		tmp := remote_request.PortList{
			Id:         val.DynamicPort,
			OriginPort: val.OriginPort,
			AccessPort: val.DynamicPort,
			Type:       val.Protocol,
		}
		if val.Protocol == consts.ProtocolHttp {
			tmp.SslEnable = "no"
		} else {
			tmp.SslEnable = "yes"
		}
		res = append(res, tmp)
	}
	return res
}

func (this DynamicServer) dealPostList(d []remote_request.PortList) []remote_request.PortList {
	var (
		res = make([]remote_request.PortList, 0)
	)
	for _, val := range d {
		if val.Type == consts.ProtocolTCP || val.Type == consts.ProtocolUdp {
			continue
		}
		res = append(res, val)
	}
	return res
}

func (this DynamicServer) convertToMySQLFields(d request.DynamicEdit, ids, cname string, tag dynamic.Dynamic, uuid string, status int) dynamic.Dynamic {
	var (
		now = time.Now().Local()
	)
	fields := dynamic.Dynamic{
		DynamicType:             d.DynamicType,
		Domains:                 d.Domains,
		Position:                d.Position,
		TenantId:                d.TenantId,
		VSTenantId:              tag.VSTenantId,
		Account:                 d.Account,
		Status:                  consts.SRunning,
		OriginIds:               ids,
		Cname:                   cname,
		CreateTime:              now,
		UpdateTime:              now,
		PackageId:               d.PackageId,
		Topo:                    d.Topo,
		IsIcp:                   d.IsIcp,
		ProxyProtocolEnable:     d.ProxyProtocolEnable,
		DisableOriginPortHeader: d.DisableOriginPortHeader,
	}
	if status != 0 {
		fields.Status = status
	}
	if uuid == "" {
		fields.ExpirationTime = tag.ExpirationTime
		fields.InstanceName = tag.InstanceName
		fields.InstanceId = tag.InstanceId
	} else {
		fields.InstanceName = d.TenantId + fmt.Sprintf("%d", now)
		fields.InstanceId = uuid
		fields.ExpirationTime = time.Unix(d.ExpirationTime, 0).Local()
	}

	originStations := make([]string, 0, len(d.OriginStations))
	for _, os := range d.OriginStations {
		originStations = append(originStations, fmt.Sprintf(innerTag, os.Address, os.IsMaster, os.CheckUrl))
	}
	fields.OriginStations = strings.Join(originStations, outTag)

	rules := make([]string, 0, len(d.Rules))
	for _, rule := range d.Rules {
		rules = append(rules, fmt.Sprintf(innerTag, rule.Protocol, rule.DynamicPort, rule.OriginPort))
	}
	fields.Rules = strings.Join(rules, outTag)

	// debug
	//marshal, _ := json.Marshal(fields)
	//fmt.Println("marshal-convertToMySQLFields", string(marshal))
	return fields
}

func (d DynamicServer) getClient() *whttp.HttpClient {
	return whttp.NewHttpClient(strings.TrimRight(ext.ExtConfig.ServiceConfig.NgvsaServiceUrl, urlTag))
}

func (d DynamicServer) getVrbmsClient() *whttp.HttpClient {
	return whttp.NewHttpClient(strings.TrimRight(ext.ExtConfig.ServiceConfig.VrbmServiceUrl, urlTag))
}

func (this DynamicServer) sqlToStuct(dynamics []dynamic.Dynamic) []request.DynamicEdit {
	var dynamicEdits []request.DynamicEdit
	for _, val := range dynamics {
		single := this.sqlToStuctSingle(val)
		dynamicEdits = append(dynamicEdits, single)
	}
	return dynamicEdits
}

func (d DynamicServer) sqlToStuctSingle(val dynamic.Dynamic) request.DynamicEdit {
	dynamicEdit := request.DynamicEdit{
		Id:                      val.Id,
		DynamicType:             val.DynamicType,
		Domains:                 val.Domains,
		Position:                val.Position,
		Topo:                    val.Topo,
		IsIcp:                   val.IsIcp,
		ProxyProtocolEnable:     val.ProxyProtocolEnable,
		DisableOriginPortHeader: val.DisableOriginPortHeader,
		TenantId:                val.TenantId,
		Account:                 val.Account,
		Status:                  val.Status,
		Cname:                   val.Cname,
		PackageId:               val.PackageId,
		InstanceName:            val.InstanceName,
		InstanceId:              val.InstanceId,
		ExpirationTime:          val.ExpirationTime.Unix(),
		VSTenantId:              val.VSTenantId,
	}

	for _, osStr := range strings.Split(val.OriginStations, outTag) {
		parts := strings.Split(osStr, spaceTag)
		if len(parts) == 3 {
			originStation := request.OriginStation{
				Address:  parts[0],
				IsMaster: parts[1],
				CheckUrl: parts[2],
			}
			dynamicEdit.OriginStations = append(dynamicEdit.OriginStations, originStation)
		}
	}

	for _, ruleStr := range strings.Split(val.Rules, outTag) {
		parts := strings.Split(ruleStr, spaceTag)
		if len(parts) == 3 {
			dynamicRule := request.DynamicRule{
				Protocol:    parts[0],
				DynamicPort: parts[1],
				OriginPort:  parts[2],
			}
			dynamicEdit.Rules = append(dynamicEdit.Rules, dynamicRule)
		}
	}
	return dynamicEdit
}

func (this DynamicServer) exist(id int64) (dynamic.Dynamic, error) {
	var (
		tmp = dynamic.Dynamic{}
	)
	err := this.Orm.Model(dynamic.Dynamic{}).
		Where("id = ?", id).
		Find(&tmp).Error
	return tmp, err
}

func (this DynamicServer) existDomain(id int64, req request.DynamicEdit) (bool, error) {
	var (
		exist bool
		tmp   = dynamic.Dynamic{}
	)
	if req.DynamicType == consts.DynamicIpType {
		for _, val := range req.Rules {
			db := this.Orm.Model(dynamic.Dynamic{})
			if id > 0 {
				db = db.Where("id != ?", id)
			}
			err := db.Where("tenantId = ?", req.TenantId).
				Where("rules LIKE ?", "%"+val.Protocol+spaceTag+val.DynamicPort+"%").
				Where("domains = ?", "").
				Find(&tmp).Error
			if err != nil {
				return false, err
			}
			if tmp.Id > 0 {
				exist = true
			}
		}

	} else {
		for _, osStr := range strings.Split(req.Domains, splitTag) {
			db := this.Orm.Model(dynamic.Dynamic{})
			if id > 0 {
				db = db.Where("id != ?", id)
			}
			err := db.Where("domains LIKE ?", "%"+osStr+"%").
				Find(&tmp).Error
			if err != nil {
				return false, err
			}
			if tmp.Id > 0 {
				exist = true
				break
			}
		}
	}
	return exist, nil
}

func (this DynamicServer) existPakId(id int64, pakId string) (bool, error) {
	var (
		exist bool
	)
	var (
		tmp = dynamic.Dynamic{}
	)
	db := this.Orm.Model(dynamic.Dynamic{})
	if id > 0 {
		db = db.Where("id != ?", id)
	}

	err := db.Where("packageId = ?", pakId).
		Find(&tmp).Error
	if err != nil {
		return false, err
	}
	if tmp.Id > 0 {
		exist = true
	}
	return exist, nil
}

func (this DynamicServer) compareDynamicRules(old, new request.DynamicEdit) (added, removed, common []request.DynamicRule) {
	var (
		addedMap   = make(map[string]bool)
		removedMap = make(map[string]bool)
		commonMap  = make(map[string]bool)
	)

	for _, newRule := range new.Rules {
		found := false
		for _, oldRule := range old.Rules {
			if newRule.Protocol == oldRule.Protocol {
				if newRule.Protocol == consts.ProtocolHttp || newRule.Protocol == consts.ProtocolHttps {
					if _, ok := commonMap[newRule.Protocol]; !ok {
						common = append(common, newRule)
						commonMap[newRule.Protocol] = true
					}
					found = true
					break
				}
				if newRule.DynamicPort == oldRule.DynamicPort {
					if _, ok := commonMap[newRule.Protocol+newRule.DynamicPort]; !ok {
						common = append(common, newRule)
						commonMap[newRule.Protocol+newRule.DynamicPort] = true
					}
					found = true
					break
				}
			}
		}
		if !found {
			if (newRule.Protocol == consts.ProtocolHttp || newRule.Protocol == consts.ProtocolHttps) && !addedMap[newRule.Protocol] {
				added = append(added, newRule)
				addedMap[newRule.Protocol] = true
			}
			if (newRule.Protocol == consts.ProtocolTCP || newRule.Protocol == consts.ProtocolUdp) && !addedMap[newRule.Protocol+newRule.DynamicPort] {
				added = append(added, newRule)
				addedMap[newRule.Protocol+newRule.DynamicPort] = true
			}
		}
	}

	for _, oldRule := range old.Rules {
		found := false
		for _, newRule := range new.Rules {
			if oldRule.Protocol == newRule.Protocol {
				if newRule.Protocol == consts.ProtocolHttp || newRule.Protocol == consts.ProtocolHttps {
					found = true
					break
				}
				if oldRule.DynamicPort == newRule.DynamicPort {
					found = true
					break
				}
			}

		}
		if !found {
			if (oldRule.Protocol == consts.ProtocolHttp || oldRule.Protocol == consts.ProtocolHttps) && !removedMap[oldRule.Protocol] {
				removed = append(removed, oldRule)
				removedMap[oldRule.Protocol] = true
			}
			if (oldRule.Protocol == consts.ProtocolTCP || oldRule.Protocol == consts.ProtocolUdp) && !removedMap[oldRule.Protocol+oldRule.DynamicPort] {
				removed = append(removed, oldRule)
				removedMap[oldRule.Protocol+oldRule.DynamicPort] = true
			}

		}
	}
	fmt.Println("added", added, "removed", removed, "common", common)
	return added, removed, common
}

func (this DynamicServer) getIds(ids string) map[string]string {
	idPairs := strings.Split(ids, splitTag)
	idMap := make(map[string]string)
	for _, pair := range idPairs {
		parts := strings.Split(pair, domainTag)
		if len(parts) == 3 {
			idMap[parts[0]+domainTag+parts[1]+domainTag] = parts[2]
		}
	}
	return idMap
}

func (this DynamicServer) getNgvsaIds(ids string) []string {
	idPairs := strings.Split(ids, splitTag)
	idMap := make([]string, 0)
	for _, pair := range idPairs {
		parts := strings.Split(pair, domainTag)
		if len(parts) == 3 {
			idMap = append(idMap, parts[2])
		}
	}
	return idMap
}

func (this DynamicServer) orderList(tenantId, orderId string) (remote_response.VrbmOrderList, error) {
	client := this.getVrbmsClient()
	reqData := struct {
		TenantId       string `json:"tenant_id"`
		RelatedProduct string `json:"related_product"`
		OrderId        string `json:"order_id"`
	}{
		TenantId:       tenantId,
		RelatedProduct: "动态加速",
		OrderId:        orderId,
	}
	r, err := client.PostJSON(vrbmOrderList, reqData)
	if err != nil {
		this.Log.Errorf("DynamicPackageList client.PostJSON error: %s \r\n", err)
		return remote_response.VrbmOrderList{}, err
	}
	response, err := whttp.HandleResponse(r)
	if err != nil {
		this.Log.Errorf("DynamicDelete whttp.HandleResponse error: %s \r\n", err.Error())
		return remote_response.VrbmOrderList{}, err
	}
	res := remote_response.VrbmOrderList{}
	err = json.Unmarshal(response, &res)
	if err != nil {
		this.Log.Errorf("DynamicDelete whttp.HandleResponse error: %s \r\n", err.Error())
		return remote_response.VrbmOrderList{}, err
	}
	return res, nil
}

func (this DynamicServer) DynamicDomainList(c *gin.Context, req request.DynamicDomainList) (interface{}, error) {
	var (
		res   = make(map[string]interface{})
		tmp   = make([]dynamic.DynamicInstance, 0)
		count int64
	)
	db := this.Orm.Model(dynamic.DynamicInstance{})
	if req.PackageId != "" {
		db = db.Where("pakId = ?", req.PackageId)
	}
	if req.InstanceId != "" {
		db = db.Where("instanceId = ?", req.InstanceId)
	}
	if req.TenantId != "" {
		db = db.Where("tenantId = ?", req.TenantId)
	}
	err := db.Preload("DynamicInfo").Count(&count).
		Offset((req.PageIndex - 1) * req.PageSize).
		Limit(req.PageSize).Find(&tmp).Error
	res["page"] = req.PageIndex
	res["size"] = req.PageSize
	res["total"] = count
	res["list"] = tmp
	return res, err
}

func (this *DynamicServer) DynamicDealRecord(c *gin.Context, req request.DynamicDealRecord) (interface{}, error) {
	//var (
	//	tmp dynamic.Dynamic
	//)
	//err := this.Orm.Model(dynamic.DynamicInstance{}).
	//	Where("id = ?", req.PackageId).
	//	Find(&tmp).Error
	//if err != nil {
	//	return nil, err
	//}
	//if tmp.Id <= 0 {
	//	return nil, nil
	//}
	if req.Action == consts.VActionDel {
		var (
			tmp dynamic.Dynamic
		)
		err := this.Orm.Model(dynamic.Dynamic{}).
			Where("packageId = ?", req.PackageId).
			Find(&tmp).Error
		if err != nil {
			return nil, err
		}
		if tmp.Id <= 0 {
			return nil, nil
		}
		reqDel := request.DynamicDel{
			Id:      tmp.Id,
			DelType: consts.VActionDel,
		}
		return this.DynamicDelete(c, reqDel)
		//return nil, this.Orm.Model(dynamic.Dynamic{}).
		//	Where("packageId = ?", req.PackageId).
		//	Delete(&dynamic.Dynamic{}).Error
	}
	now := time.Now()
	uid := uuid.NewString()
	fields := dynamic.Dynamic{
		TenantId:       req.TenantId,
		VSTenantId:     req.VSTenantId,
		Account:        req.TenantId,
		Status:         consts.STrans,
		PackageId:      req.PackageId,
		CreateTime:     now,
		UpdateTime:     now,
		ExpirationTime: time.Unix(req.ExpirationTime, 0).Local(),
		//InstanceName:   req.TenantId + "-" + now.Format("20060102"),
		InstanceName: uid,
		InstanceId:   uid,
	}
	return nil, this.Orm.Model(dynamic.Dynamic{}).Create(&fields).Error
}

func (this DynamicServer) AreaList(c *gin.Context, req request.DynamicDealRecord) (interface{}, error) {
	hClient := this.getClient()
	r, err := hClient.Get("/v1/area/list")
	if err != nil {
		return nil, err
	}
	response, err := whttp.HandleResponse(r)
	if err != nil {
		this.Log.Errorf("AreaList whttp.HandleResponse error: %s \r\n", err)
		return nil, err
	}
	res := remote_response.DynamicCommon{}
	json.Unmarshal(response, &res)
	if res.Code != 200 {
		this.Log.Errorf("DynamicEdit whttp.HandleResponse error: %v \r\n", string(response))
		return nil, ngvsaErr
	}
	return res.Data, nil
}

func (this DynamicServer) TopoArea(c *gin.Context, req request.DynamicDealRecord) (interface{}, error) {
	hClient := this.getClient()
	r, err := hClient.Get("/v1/area/topoArea/topo?area_id=" + c.Request.URL.Query().Get("area_id") + "&is_icp=" + c.Request.URL.Query().Get("is_icp"))
	if err != nil {
		return nil, err
	}
	response, err := whttp.HandleResponse(r)
	if err != nil {
		this.Log.Errorf("AreaList whttp.HandleResponse error: %s \r\n", err)
		return nil, err
	}
	res := remote_response.DynamicCommon{}
	json.Unmarshal(response, &res)
	if res.Code != 200 {
		this.Log.Errorf("DynamicEdit whttp.HandleResponse error: %v \r\n", string(response))
		return nil, ngvsaErr
	}
	return res.Data, nil
}

func (this DynamicServer) SpecialTenantList(c *gin.Context, req request.SpecialTenantList) (interface{}, error) {
	var (
		tmp = make([]dynamic.DynamicInstance, 0)
	)
	db := this.Orm.Model(dynamic.DynamicInstance{}).
		Where("ngvsaInstanceId != ''")
	if req.TenantId != "" {
		db.Where("tenantId = ?", req.TenantId)
	}
	if req.VSTenantId != "" {
		//db.Where("", req.VSTenantId)
		db.Where("vsTenantId = ?", req.VSTenantId)
	}
	if req.ProtocolType == "layer4" {
		db.Where("protocol='layer4' Or protocol='layer4udp'")
	}
	if req.ProtocolType == "layer7" {
		db.Where("protocol='ssl' Or protocol='non_ssl'")
	}
	if req.InstanceId != "" {
		db.Where("instanceId=?", req.InstanceId)
	}
	err := db.Find(&tmp).Error
	if err != nil {
		return nil, err
	}
	var (
		instances = make([]string, 0)
	)
	for _, val := range tmp {
		if val.NgvsaInstanceId != "" {
			instances = append(instances, val.NgvsaInstanceId)
		}
	}
	return instances, nil
	//uPorts := wtools.SliceUnique(ports)
	//uDomains := wtools.SliceUnique(domains)
	//if req.ProtocolType == "layer4" {
	//	return uPorts, nil
	//}
	//return uDomains, nil
}

func (this DynamicServer) VcfnCnameList(c *gin.Context) (interface{}, error) {
	var (
		err               error
		vcfnRootDomainMap = make(map[string]string)
	)
	path := "envconfig/vcfn_root_doamin.json"
	if wtools.PathExists("/usr/local/vrcm/envconfig/") {
		path = "/usr/local/vrcm/envconfig/vcfn_root_doamin.json"
	}
	defer func() {
		if err != nil {
			fmt.Println("===> Give The Default Root Domain, Err" + err.Error())
			vcfnRootDomainMap = map[string]string{
				"cctv":       "cctv.vrx.videosolar.com",
				"cctvawsno3": "cctv.vrx.videosolar.com",
			}
		}
	}()
	file, err := os.Open(path)
	defer file.Close()
	if err != nil {
		return vcfnRootDomainMap, nil
	}
	fileInfo, err := file.Stat()
	if err != nil {
		return vcfnRootDomainMap, nil
	}
	fileSize := fileInfo.Size()
	buffer := make([]byte, fileSize)
	_, err = file.Read(buffer)
	if err != nil {
		return vcfnRootDomainMap, nil
	}
	json.Unmarshal(buffer, &vcfnRootDomainMap)
	return vcfnRootDomainMap, nil
}

func (this DynamicServer) createDILog(req request.DynamicEdit, uid string, idM map[string]string, cname, vsTenantId string) error {
	if req.DynamicType == consts.DynamicIpType {
		return this.createDILogLayer4(req, uid, idM, cname)
	}
	dms := strings.Split(req.Domains, splitTag)
	var (
		cDta = make([]dynamic.DynamicInstance, 0)
		now  = time.Now()
	)
	for _, val := range dms {
		for _, v := range req.Rules {
			// 获取其 proxy port
			tmp := dynamic.DynamicInstance{
				InstanceId: uid,
				Domain:     val,
				CreateTime: now,
				TenantId:   req.TenantId,
				VSTenantId: vsTenantId,
				PakId:      req.PackageId,
				Protocol:   v.Protocol,
				Port:       v.DynamicPort,
				//IsSystem:   v.IsSystem,
			}
			if v.Protocol == consts.ProtocolTCP || v.Protocol == consts.ProtocolUdp {
				//proxyPort, err := this.getProxyPort(v.Protocol, v.DynamicPort)
				//if err != nil {
				//	return err
				//}
				tmp.NgvsaInstanceId = idM[val+domainTag+v.Protocol+v.DynamicPort+domainTag]
				//tmp.ProxyPort = proxyPort
			} else {
				tmp.NgvsaInstanceId = idM[val+domainTag+v.Protocol+domainTag]
			}

			tag := dynamic.DynamicInstance{}
			err := this.Orm.Model(dynamic.DynamicInstance{}).
				Where("instanceId = ?", uid).
				Where("domain = ?", val).
				Where("port = ?", v.DynamicPort).
				Where("protocol = ?", v.Protocol).
				Where("ngvsaInstanceId = ?", tmp.NgvsaInstanceId).
				Find(&tag).
				Error
			if err != nil {
				this.Log.Errorf("createDILog error(%s): %s, log-tag-id: %d\r\n", val, err.Error(), tag.ID)
				return errors.New("create Instance Log Err")
			}
			if tag.ID > 0 {
				//if tag.IsSystem == "own" && tmp.IsSystem == "system" {
				//	err = this.Orm.Model(dynamic.DynamicInstance{}).
				//		Where("id = ?", tag.ID).
				//		Update("isSystem", "system").Error
				//}
				this.Log.Errorf("target domain already exist %s tagID: %s\r\n", val, tag.ID)
				continue
			}
			cDta = append(cDta, tmp)
			time.Sleep(time.Millisecond * 20)
		}
	}
	if len(cDta) == 0 {
		return nil
	}
	return this.Orm.Model(dynamic.DynamicInstance{}).Create(&cDta).Error
}

func (this DynamicServer) createDILogLayer4(req request.DynamicEdit, uid string, idM map[string]string, cname string) error {
	var (
		cDta = make([]dynamic.DynamicInstance, 0)
		now  = time.Now()
	)
	for _, v := range req.Rules {
		var (
			proxyPort string
		)
		tmp := dynamic.DynamicInstance{
			InstanceId: uid,
			Domain:     "",
			CreateTime: now,
			TenantId:   req.TenantId,
			PakId:      req.PackageId,
			Protocol:   v.Protocol,
			Port:       v.DynamicPort,
			ProxyPort:  proxyPort,
			//IsSystem:   v.IsSystem,
		}
		tmp.NgvsaInstanceId = idM[cname+domainTag+v.Protocol+v.DynamicPort+domainTag]
		// 获取其 proxy port
		//proxyPort, err := this.getProxyPort(v.Protocol, v.DynamicPort)
		//if err != nil {
		//	return err
		//}
		tag := dynamic.DynamicInstance{}
		err := this.Orm.Model(dynamic.DynamicInstance{}).
			Where("instanceId = ?", uid).
			Where("domain = ?", "").
			Where("port = ?", v.DynamicPort).
			Where("tenantId = ?", req.TenantId).
			Where("protocol = ?", v.Protocol).
			//Where("proxyPort = ?", proxyPort).
			Where("ngvsaInstanceId = ?", tmp.NgvsaInstanceId).
			Find(&tag).
			Error
		if err != nil {
			this.Log.Errorf("createDILogLayer error(%s): %s, log-tag-id: %d\r\n", "", err.Error(), tag.ID)
			return errors.New("create Instance Log Err")
		}
		if tag.ID > 0 {
			this.Log.Errorf("target domain already exist %s tagID: %s\r\n", "", tag.ID)
			continue
		}

		cDta = append(cDta, tmp)
		time.Sleep(time.Millisecond * 20)
	}
	if len(cDta) == 0 {
		return nil
	}
	return this.Orm.Model(dynamic.DynamicInstance{}).Create(&cDta).Error
}

func (this *DynamicServer) getProxyPort(proxy, port string) (string, error) {
	hClient := this.getClient()
	r, err := hClient.Get(porxyPortPath)
	if err != nil {
		this.Log.Errorf("getProxyPort error: %s \r\n", err)
		return "", err
	}
	response, err := whttp.HandleResponse(r)
	if err != nil {
		this.Log.Errorf("getProxyPort whttp.HandleResponse error: %s \r\n", err)
		return "", err
	}
	res := remote_response.NgvsaPort{}
	json.Unmarshal(response, &res)
	if res.Code != 200 {
		this.Log.Errorf("DynamicDelete whttp.HandleResponse Code error: %v \r\n", res)
		return "", ngvsaErr
	}
	var (
		target string
	)
	for _, val := range res.Data.Rows {
		if val.AccessPort == port && val.Type == proxy {
			target = val.ProxyPort
			break
		}
	}
	return target, nil
}

func getOwnDomain(t, vst string) string {
	randStr := wtools.Randn(6)
	if vst != "" {
		if val, ok := rootDomainMap[vst]; ok {
			return randStr + "." + val
		}
		return randStr + "." + rootDomainMap["default"]
	}
	if val, ok := rootDomainMap[t]; ok {
		return randStr + "." + val
	}
	return randStr + "." + rootDomainMap["default"]
}

func init() {
	once.Do(func() {
		getRootDomain()
		fmt.Println("===> getRootDomain ===> ")
		fmt.Println(rootDomainMap)
		fmt.Println("===> getRootDomain ===> ")

	})
}

func byId(p1, p2 *request.DynamicEdit) bool {
	return p1.Id > p2.Id
}

func (this DynamicServer) setSingleWithSystemTag(dInfo dynamic.Dynamic, reqInfo request.DynamicEdit) request.DynamicEdit {
	idMaps := this.getIds(dInfo.OriginIds)
	for key, _ := range reqInfo.Rules {
		if reqInfo.Rules[key].Protocol == consts.ProtocolHttp || reqInfo.Rules[key].Protocol == consts.ProtocolHttps {
			continue
		}
		var (
			tmp dynamic.DynamicInstance
		)
		ngvsaId := idMaps[dInfo.Cname+domainTag+reqInfo.Rules[key].Protocol+reqInfo.Rules[key].DynamicPort+domainTag]
		err := this.Orm.Model(dynamic.DynamicInstance{}).
			Where("instanceId = ?", dInfo.InstanceId).
			Where("tenantId = ?", dInfo.TenantId).
			Where("protocol = ?", reqInfo.Rules[key].Protocol).
			Where("port = ?", reqInfo.Rules[key].DynamicPort).
			Where("ngvsaInstanceId = ?", ngvsaId).
			Find(&tmp).Error
		if err != nil {
			this.Log.Errorf("setSingleWithSystemTag error: %s \r\n", err)
			continue
		}
		//if err == nil && tmp.ID > 0 {
		//	reqInfo.Rules[key].IsSystem = tmp.IsSystem
		//}
	}
	return reqInfo
}

func getRootDomain() {
	var (
		err error
	)
	path := "envconfig/root_domain.json"
	if wtools.PathExists("/usr/local/vrcm/envconfig/") {
		path = "/usr/local/vrcm/envconfig/root_domain.json"
	}
	defer func() {
		if err != nil {
			fmt.Println("===> Give The Default Root Domain, Err" + err.Error())
			rootDomainMap = map[string]string{
				"default": "vrx.videosolar.net",
			}
		}
	}()
	file, err := os.Open(path)
	defer file.Close()
	if err != nil {
		return
	}
	fileInfo, err := file.Stat()
	if err != nil {
		return
	}
	fileSize := fileInfo.Size()
	buffer := make([]byte, fileSize)
	_, err = file.Read(buffer)
	if err != nil {
		return
	}
	json.Unmarshal(buffer, &rootDomainMap)
	return
}
